﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Configuration;
using System.IO;
using Ue.Core.FileSystems;
using Ue.Eagle.Runtime.FileSystems;
using Ue.Eagle.Runtime.Configuration;
using Ue.Eagle.Runtime.Models;

namespace Ue.Eagle.Runtime.Folders
{
    public class PluginHarvester : IPluginHarvester
    {
        private readonly IRootFolder folder;

        public PluginHarvester(IRootFolder folder)
        {
            this.folder = folder;
        }

        #region IPluginHarvester 成员

        public PluginDescriptor HarvestPlugin(string path, string manifestName)
        {
            var pluginSection = this.GetPluginSection(path, manifestName);
            if (pluginSection == null)
            {
                return null;
            }

            var extensionPoints = pluginSection.ExtensionPoints
                .OfType<PluginExtenisonPointElement>()
                .Select(e => {
                    return new PluginExtensionPoint(
                        string.Format("{0}.{1}", pluginSection.Id, e.Name),
                        e.Name,
                        e.ExtensionConfigurationElementType);
                });

            var extensions = pluginSection.Extensions
                .OfType<PluginExtensionElement>()
                .Select(e => new PluginExtension(e));

            return new PluginDescriptor(
                pluginSection.Id,
                pluginSection.Name,
                pluginSection.Author,
                pluginSection.Version,
                pluginSection.Description,
                extensionPoints,
                extensions,
                path);
        }

        #endregion

        private PluginSection GetPluginSection(string path, string manifestName)
        {
            var physicalPath = folder.CombineToPhysicalPath(path, manifestName);

            if (!File.Exists(physicalPath))
            {
                return null;
            }

            try
            {
                ConfigurationFileMap fileMap = new ConfigurationFileMap(physicalPath);

                return ConfigurationManager.OpenMappedMachineConfiguration(fileMap)
                    .GetSection(PluginConfigurationConstants.PluginConfigurationSectionName) as PluginSection;
            }
            catch (ConfigurationErrorsException)
            {
                return null;
            }
        }
    }
}
